package org.webball.main;

import java.io.IOException;
import java.net.UnknownHostException;

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;

import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.SlickException;
import org.webball.communication.Communication;
import org.webball.player.Player;



public class PlayersSkillsWindow extends JFrame
{
	private Communication comm;
	
	private int number = 0;								// number of currently edited player
	private int nop = 5;								// number of players in the team, counting from 0	
	private Player[] players = new Player[nop+1];		// array of chosen players skills
	private JFrame window;								// handle to this window
	private int teamN;
	
	private int points_left=30;							// how many points are left
	
	private JPanel panel = new JPanel();				// main panel of the window
	private JLabel label = new JLabel();				// which player is currently edited
	private JLabel label2 = new JLabel();				// label that contains number of points which are left
	private JSlider sliders[] = new JSlider[nop+1];		// sliders used to assign values to players skills
	private int prev[] = {0, 0, 0, 0, 0};				// preview values of sliders
	
	
	
	PlayersSkillsWindow(Communication comm, int teamN)
	{		
		super("Skill Change Window");
		window = this;		// will be needed to close the window by program
		
		this.comm = comm;
		this.teamN = teamN;
		
		updateView();		// adds all components to the main panel
		
		add(panel);
		
		pack();				// sets the automatic size of the window so that all components may fit there
		setVisible(true);
		setResizable(false);
		setLocationRelativeTo(null);	// sets window position to the center of the screen
	}
	
	
	
	void updateView()
	{
		// this class handles the interaction with the slider via mouse
		MouseAdapter sliderValueChanged_m = new MouseAdapter()
		{
			int curr;	// current value of slider, read after mouse had stopped
			int i;		// variable that points out which slider value has changed because of the move
			
			public void mouseReleased(MouseEvent e)
			{
				JSlider source = (JSlider)e.getSource();
				curr = source.getValue();
				
				for(int s=1; s<=nop; s++)
				{
					if (sliders[s] == source)
						i = s-1;
				}
				
	    		key_or_mouse_released(source, prev[i], curr);		// change adequate labels and slider values
	    		prev[i] = source.getValue();						// save current value so it can be used in the next move
	    	}
		};
		
		// this class handles the interaction with the slider via keyboard
		KeyAdapter sliderValueChanged_key = new KeyAdapter()
		{
			int prev;					// value of the slider before the move
			int curr;					// value of the slider; read after the move had finished
			Boolean pressed = false;	// variable used to identify if the key is pressed or not
			
			public void keyPressed(KeyEvent e)
			{
				JSlider source = (JSlider)e.getSource();
				if (pressed == false)
				{
					prev = source.getValue();
					pressed = true;
				}
			}
			
			public void keyReleased(KeyEvent e)
			{
				JSlider source = (JSlider)e.getSource();
				curr = source.getValue();
	    		key_or_mouse_released(source, prev, curr);	// change adequate labels and slider values
	    		pressed = false;
	    		update_prevs(source, curr);					// communicate with mouseAdapter to keep up to date preview values
			}
		};
		
		ActionListener nextPlayer = new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				Player tp = new Player();						// create new player
				tp.setPower(sliders[1].getValue());				// fill it with data
				tp.setSpeed(sliders[2].getValue());
				tp.setAttackPrecision(sliders[3].getValue());
				tp.setPassPrecision(sliders[4].getValue());
				tp.setServePrecision(sliders[5].getValue());
				players[number] = tp;							// add the player to the array
				number++;
				
				if ((number-1) != nop)
				{
					updateView();								// fill the window with new data for another player
				}
				else
				{	
					window.dispose();							// or close the window and go to the next step in the game
					
					AppGameContainer app;
					try
					{
						app = new AppGameContainer(new Game("Webball", comm, players, teamN));
						app.setMaximumLogicUpdateInterval(10);
		                app.setMinimumLogicUpdateInterval(50);
		                app.setVSync(true);
		                app.setTargetFrameRate(35);                
		                app.setDisplayMode(800, 600, false);
		                app.start();
					}
					catch (SlickException e1) {e1.printStackTrace();}
				}
				
			}
		};
		
		for (int p=0; p<=4; p++)
		{
			prev[p] = 0;		// initialize preview values with zeros when creating new window
		}
		
		Border empty = BorderFactory.createEmptyBorder();
		TitledBorder title;
		
		points_left = 30;
		
		panel.removeAll();		// empty panel of previous contents
		
		panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
		panel.setBorder(BorderFactory.createEmptyBorder(30,30,25,30));
		
		JPanel upper = new JPanel();		// upper panel contains everything above sliders
		upper.setLayout(new BoxLayout(upper, BoxLayout.X_AXIS));
		
		ImageIcon theIcon = new ImageIcon("player.png");
		JButton player_image = new JButton("", theIcon);
		player_image.setBorder(empty);
		upper.add(player_image);
		
		JPanel upper_right = new JPanel(new GridLayout(2,1));	// upper_right panel contains labels and titles about player and points that are left
		upper_right.setBorder(BorderFactory.createEmptyBorder(20,30,20,0));
		
		label.setText("Payer no. " +  (number+1));
		label.setAlignmentX(CENTER_ALIGNMENT);
		label.setFont(label.getFont().deriveFont(24.0f));
		upper_right.add(label);
		
		label2.setText("There are " + points_left + " points left.");
		label2.setAlignmentX(CENTER_ALIGNMENT);
		label2.setFont(label2.getFont().deriveFont(15.0f));
		upper_right.add(label2);
		
		upper.add(upper_right);
		panel.add(upper);
		
		panel.add(new JPanel());
		panel.add(new JPanel());
		
		// initialize and show the sliders
		for(int s=1; s<=5; s++)
		{
			sliders[s] = new JSlider();
			sliders[s].setMaximum(10);
			sliders[s].setValue(0);
			sliders[s].addMouseListener(sliderValueChanged_m);
			sliders[s].addKeyListener(sliderValueChanged_key);
			sliders[s].setMinorTickSpacing(1);
			sliders[s].setMajorTickSpacing(5);
			sliders[s].setPaintTicks(true);
			sliders[s].setSnapToTicks(true);
			
			String title_text;
			
			switch(s)
			{
				case 1:
					title_text = "Power = 0";
					break;
				case 2:
					title_text = "Speed = 0";
					break;
				case 3:
					title_text = "Attack precision = 0";
					break;
				case 4:
					title_text = "Pass precision = 0";
					break;
				default:
					title_text = "Serve precision = 0";
					break;
			}
			
			title = BorderFactory.createTitledBorder(empty, title_text);
			title.setTitlePosition(TitledBorder.TOP);
			sliders[s].setBorder(title);
			
			panel.add(sliders[s]);
			panel.add(new JPanel());
		}
		
		panel.add(new JPanel());
		
		JPanel buttons = new JPanel();			// buttons panel contains "next" button
		buttons.setLayout(new GridLayout(1,3));
		buttons.add(new JPanel());
		buttons.add(new JPanel());
		
		JButton next;
		if (number != nop)
		{
			next = new JButton("Next player");
		}
		else
		{
			next = new JButton("I've finished!");
		}
		next.addActionListener(nextPlayer);
		
		buttons.add(next);
		
		panel.add(buttons);
		panel.updateUI();
	}
	
	
	
	// method used to keep the preview slider values up to date so there is no conflict between mouse and keyboard usage
	public void update_prevs(JSlider source, int p)
	{
		int i=0;
		
		for(int s=1; s<=nop; s++)
		{
			if (sliders[s] == source)
				i = s-1;
		}
		
		prev[i] = p;
	}
	
	
	
	void key_or_mouse_released(JSlider source, int prev, int curr)
	{
		// check if the value of the given slider has lowered
		if (prev > curr)
		{
			points_left += (prev - curr);
		}
		// or if the value of the given slider has risen
		else if (prev < curr)
		{
			// and if it has risen then check if there is enough points to assign to a slider
			if ((curr - prev) <= points_left)
			{
				points_left -= (curr - prev);
			}
			// and if there is less points left than user demands then lower the slider value to the appropriate one 
			else
			{
				source.setValue(prev + points_left);
				points_left = 0;
			}
		}
		label2.setText("There are " + points_left + " points left.");
		
		// update the title displayed above given slider so it contains up to date value
		TitledBorder t = (TitledBorder) source.getBorder();
		String s = t.getTitle();
		int index = s.indexOf('=');
		String s2 = s.substring(0, index);
		s2 = s2 + "= " + source.getValue();
		t.setTitle(s2);
		source.setBorder(t);
		panel.updateUI();
		// ---
	}

	
	
	/*
	public static void main(String[] args)
	{
		javax.swing.SwingUtilities.invokeLater(new Runnable()
		{
			public void run()
			{
				try
				{
					new PlayersSkillsWindow(new Communication("127.0.0.1", 1234));
				}
				catch (UnknownHostException e)	{e.printStackTrace();}
				catch (IOException e)			{e.printStackTrace();}
			}
		});
	}
	*/
}